iT邦幫忙

2023 iThome 鐵人賽

DAY 4
0
SideProject30

用 Rails 打造你的電商網站系列 第 4

Day 04 增加圖片功能讓網站更吸睛

  • 分享至 

  • xImage
  •  

完成個人檔案頁面後,但好像少了些什麼?

啊!使用者沒有大頭貼啦

我們就來做圖片上傳功能吧!

Rails 有個好用的圖片上傳功能,叫做 Active Storage

我們會搭配 Active Storage 以及 S3 來做

一樣請依照官方來安裝所需要的套件 image_processing 以及 active_storage

特別說明一下,安裝完 active_storage 後,會產出 active_storage_blobs active_storage_variant_records active_storage_attachments 這三個 table

稍微介紹一下他們個別的作用:

active_storage_blobs 會存放檔案的基本資訊,例如檔案名稱、存放的 server、檔案大小、檔案格式

active_storage_variant_records 處理檔案的各種不同 size 及格式

active_storage_attachments 使用 polymorphic 的方式來記錄檔案是屬於哪個 model 的

設定上傳的 server

我們這次使用的是 amazon 的 S3 服務,所以就把 amazon 註解區塊解除掉

# storage.yml

amazon:
  service: S3
  access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %>
  secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %>
  region: us-east-1
  bucket: your_own_bucket-<%= Rails.env %>

要使用 S3 服務,我們就必須去註冊一個 amazon 的帳號密碼,並且取得 key 的資料

設定 S3

Step 1. 建立一個新的 bucket

https://ithelp.ithome.com.tw/upload/images/20230919/20150947h76SDiL7JL.png

Bucket name 填寫名字
AWS Region 指的是伺服器位置,可以選擇你習慣用的

Step 2. 設定物件的存取

https://ithelp.ithome.com.tw/upload/images/20230919/20150947HtJWxfgJX7.png

ACLs enabled - 只有此帳號才可以存取這個物件(較嚴謹),不過選擇這個的話,三不五時就會需要 token 來驗證,應該會非常困擾
ACLs disabled - 其他用戶都可以存取這個物件

Step 3. 物件阻擋設定

在上一步我們將物件開放給其他用戶存取,不過在這個區塊我們可以來阻擋一些權限,來增加一點安全性

https://ithelp.ithome.com.tw/upload/images/20230919/20150947IidYYMXABY.png

Block public access to buckets and objects granted through new access control lists (ACLs): 阻擋新的 ACLs 存取權

Block public access to buckets and objects granted through any access control lists (ACLs):阻擋所有 ACLs 存取權

Block public access to buckets and objects granted through new public bucket or access point policies:只有授權的人才能存取

Block public and cross-account access to buckets and objects through any public bucket or access point policies:禁止跨帳戶存取

我們只要勾下面三項就好,最後勾選免責聲明書?

接下來都套用預設就好了,我們就可以到下一步了

創建成功後,我們必須要來設定 S3 檔案的權限

Step 4. 至 IAM 頁面

https://ithelp.ithome.com.tw/upload/images/20230919/201509472BncPPeMhj.png

點選 Policies

https://ithelp.ithome.com.tw/upload/images/20230919/20150947bXCqBAhhFB.png

Step 5. 建立 policy

右邊有個 create policy 藍色按鈕,點下去

https://ithelp.ithome.com.tw/upload/images/20230919/20150947g3sgmtLRBO.png

我們要設定的是 S3 ,就選擇 S3

接下來我們就要設定用戶可以針對物件做些什麼事情(可以參考 Rails 建議設定)

讓用戶可以存取到圖片,所以要選擇 List 中的 ListBucket

讓用戶可以讀取圖片,所以要選擇 Read 中 GetObject

讓用戶可以上傳圖片,所以選擇 Write 中 PutObject

接下來是要讓所有人都可以存取,需要給他 ACL 存取,選擇 Permissions management 中的 PutObjectAcl

下方要指定 bucket 給他,在 bucket 這個地方選擇 Add Arn

https://ithelp.ithome.com.tw/upload/images/20230919/20150947FX5I5pf44i.png

接下來要設定 bucket 哪些檔案套用上方的 policy

https://ithelp.ithome.com.tw/upload/images/20230919/20150947sMfNWHUiUm.png

點選下一步後,填寫名稱就建立完成了
https://ithelp.ithome.com.tw/upload/images/20230919/20150947iGxOXT0BJL.png

Step 6. 建立 User

設定完 Policy 後,我們要來設定 User,並且拿取 key

我們到 IAM 底下的 User

https://ithelp.ithome.com.tw/upload/images/20230919/20150947LdiKtFZTIR.png

右方有個橘色 create user 的按鈕,點選下去

https://ithelp.ithome.com.tw/upload/images/20230919/201509477nHthb9bWk.png

幫 user 命名後點選下一步

https://ithelp.ithome.com.tw/upload/images/20230919/20150947Ie0oes3Zh4.png

在這邊我們要設定 policy 給這個 user,所以點選 Attach policies directly

接下來在 Permission policies 搜尋剛剛你做的 policy 的名字

https://ithelp.ithome.com.tw/upload/images/20230919/201509477KltXv0iQ3.png

選取後下一步,沒有額外要設定的話就可以直接 create user 了

拿取 key

user 建立後,我們可以點選進去,選擇 security credentials

到 Access keys 區塊,點選 Create access key

https://ithelp.ithome.com.tw/upload/images/20230919/20150947NZwWAkrKPH.png

選擇 Application running outside AWS,

點選下一步後,再點選 create 就可以囉

https://ithelp.ithome.com.tw/upload/images/20230919/20150947jl0CfgUMi5.png

複製 access key 及 secret access key

放置到環境變數中

設定 active storage 的 server

設定成 amazon 後,他就會去 storage.yml 檔案中找 amazon 的設定

# config/environments/development.rb

  config.active_storage.service = :amazon

設定完也要記得更新 storage.yml 喔

應該只要更新 access_key_id 及 secret_access_key 及 bucket

這邊的環境變數是使用預設的 master.key 來存取(若你是使用 master.key 就可以沿用)

如果是使用 dotenv 來存取環境變數,就必須改寫法

# config/storage.yml

service: S3
  access_key_id: <%= ENV['AMAZON_ACCESS_KEY'] %>
  secret_access_key: <%= ENV['AMAZON_SECRET_ACCESS_KEY'] %>
  region: us-east-1
  bucket: test-sideproject

安裝 aws-sdk-s3 套件

AWS 提供的工具,讓我們可在應用程式中使用 S3

gem "aws-sdk-s3", require: false

設定 CORS

因為是跨網存取服務,我們必須要在 S3 中設定,不然就會被 Rails 擋下

到 S3 > bucket > 點選你的 bucket > Permissions

拉到最下面會有個 CORS 區塊,點選 edit,並將這串貼上修改

AllowedHeaders: 哪些 Header 是被允許的

AllowedMethods: 哪些 HTTP 方法(GET、POST、PUT、DELETE等)被允許用來訪問 S3

AllowedOrigins: 哪些網域被允許訪問 S3

ExposeHeaders: 指定哪些 Header 會放在回應中,讓前端 JavaScript 程式碼可以訪問這些 Header

MaxAgeSeconds: 瀏覽器應該將 CORS 規則緩存多長時間,在這個時間內,瀏覽器不需要對同一個資源發出另一個請求

[
  {
    "AllowedHeaders": [
      "*"
    ],
    "AllowedMethods": [
      "PUT"
    ],
    "AllowedOrigins": [
      "https://127.0.0.1:3000"
    ],
    "ExposeHeaders": [
      "Origin",
      "Content-Type",
      "Content-MD5",
      "Content-Disposition"
    ],
    "MaxAgeSeconds": 3600
  }
]

設定完即可存檔

增加圖片關聯

在個人檔案的 model 中加入 has_one_attached

# app/modle/profile.rb

class Profile < ApplicationRecord
  belongs_to :user

  has_one_attached :avatar
end

接著我們可以到昨天做的 component 中,把大頭貼的欄位塞進去

# app/components/profile_form_component.html.erb

  <div class="flex items-center mb-4 field">
    <%= f.label :avatar, '大頭貼' , class: 'mr-4' %><br />
    <%= f.file_field :avatar, class: 'rounded-md' %>
  </div>

接下來到 controller 中,在 params 裡面也要記得加入

# app/controllers/profiles_controller.rb

def profile_params
    params.require(:profile).permit(:name, :address, :phone, :gender, :birthday, :avatar).merge(user: current_user)
  end

因為我們剛剛做了蠻多設定上的調整,所以重開 server

試試上傳功能

送出之後應該就成功囉

今天篇幅比較長,在 view 裡面的存取就另一篇再說吧!


上一篇
Day 03 用一塊一塊的積木堆積成一個網站
下一篇
Day 05 - 把機密資訊放到保險櫃中
系列文
用 Rails 打造你的電商網站30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言